package com.skjanyou.applicationcase.util;

import java.awt.AWTException;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
/**
 * 屏幕上查找指定图片
 * @author Jeby Sun
 * @date 2014-09-13
 * @website http://www.jebysun.com
 */
public class ImageFindUtil {

	BufferedImage tocompareImage;  //屏幕截图
	BufferedImage keyImage;      //查找目标图片

	int tocompareWidth;       //屏幕截图宽度
	int tocompareHeight;       //屏幕截图高度

	int keyImgWidth;         //查找目标图片宽度
	int keyImgHeight;         //查找目标图片高度

	int[][] tocompareImageRGBData;  //屏幕截图RGB数据
	int[][] keyImageRGBData;     //查找目标图片RGB数据

	/**
	 * 
	 * @param keyImagePath 为需要找图的图片的位置，一般比下面的图片要小
	 * @param image  从这张图片里面找上面的图片，一般比上面的要大
	 * 
	 */
	public ImageFindUtil(String keyImagePath,BufferedImage image) {
		tocompareImage = this.getFullScreenShot();
		keyImage = this.getBfImageFromPath(keyImagePath);
		tocompareImageRGBData = this.getImageGRB(tocompareImage);
		keyImageRGBData = this.getImageGRB(keyImage);
		tocompareWidth = tocompareImage.getWidth();
		tocompareHeight = tocompareImage.getHeight();
		keyImgWidth = keyImage.getWidth();
		keyImgHeight = keyImage.getHeight();
	}
	/**
	 * 
	 * @param keyImagePath 为需要找图的图片的位置，是在当前屏幕截图进行比较
	 * 
	 */
	public ImageFindUtil(String keyImagePath) {
		tocompareImage = this.getFullScreenShot();
		keyImage = this.getBfImageFromPath(keyImagePath);
		tocompareImageRGBData = this.getImageGRB(tocompareImage);
		keyImageRGBData = this.getImageGRB(keyImage);
		tocompareWidth = tocompareImage.getWidth();
		tocompareHeight = tocompareImage.getHeight();
		keyImgWidth = keyImage.getWidth();
		keyImgHeight = keyImage.getHeight();
	}

	/**
	 * 全屏截图
	 * @return 返回BufferedImage
	 */
	public BufferedImage getFullScreenShot() {
		BufferedImage bfImage = null;
		int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
		int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
		try {
			Robot robot = new Robot();
			bfImage = robot.createScreenCapture(new Rectangle(0, 0, width, height));
		} catch (AWTException e) {
			e.printStackTrace();
		}
		return bfImage;
	}

	/**
	 * 从本地文件读取目标图片
	 * @param keyImagePath - 图片绝对路径
	 * @return 本地图片的BufferedImage对象
	 */
	public BufferedImage getBfImageFromPath(String keyImagePath) {
		BufferedImage bfImage = null;
		try {
			bfImage = ImageIO.read(new File(keyImagePath));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bfImage;
	}

	/**
	 * 根据BufferedImage获取图片RGB数组
	 * @param bfImage
	 * @return
	 */
	public int[][] getImageGRB(BufferedImage bfImage) {
		int width = bfImage.getWidth();
		int height = bfImage.getHeight();
		int[][] result = new int[height][width];
		for (int h = 0; h < height; h++) {
			for (int w = 0; w < width; w++) {
				//使用getRGB(w, h)获取该点的颜色值是ARGB，而在实际应用中使用的是RGB，所以需要将ARGB转化成RGB，即bufImg.getRGB(w, h) & 0xFFFFFF。
				result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF;
			}
		}
		return result;
	}


	/**
	 * 查找图片
	 */
	public List<Point> findImage() {
		List<Point> points = new ArrayList<Point>();
		//遍历屏幕截图像素点数据
		for(int y=0; y<tocompareHeight-keyImgHeight; y++) {
			for(int x=0; x<tocompareWidth-keyImgWidth; x++) {
				//根据目标图的尺寸，得到目标图四个角映射到屏幕截图上的四个点，
				//判断截图上对应的四个点与图B的四个角像素点的值是否相同，
				//如果相同就将屏幕截图上映射范围内的所有的点与目标图的所有的点进行比较。
				if((keyImageRGBData[0][0]^tocompareImageRGBData[y][x])==0
						&& (keyImageRGBData[0][keyImgWidth-1]^tocompareImageRGBData[y][x+keyImgWidth-1])==0
						&& (keyImageRGBData[keyImgHeight-1][keyImgWidth-1]^tocompareImageRGBData[y+keyImgHeight-1][x+keyImgWidth-1])==0
						&& (keyImageRGBData[keyImgHeight-1][0]^tocompareImageRGBData[y+keyImgHeight-1][x])==0) {

					boolean isFinded = isMatchAll(y, x);
					//如果比较结果完全相同，则说明图片找到，填充查找到的位置坐标数据到查找结果数组。
					if(isFinded) {
						int x_top = x;
						int y_top = y;
						points.add(new Point(x_top,y_top));
						int xx = x + keyImgWidth - 1;
						int yy = y + keyImgHeight - 1;
						points.add(new Point(xx,yy));
					}
				}
			}
		}
		return points;
	}

	/**
	 * 判断屏幕截图上目标图映射范围内的全部点是否全部和小图的点一一对应。
	 * @param y - 与目标图左上角像素点想匹配的屏幕截图y坐标
	 * @param x - 与目标图左上角像素点想匹配的屏幕截图x坐标
	 * @return
	 */
	public boolean isMatchAll(int y, int x) {
		int biggerY = 0;
		int biggerX = 0;
		int xor = 0;
		for(int smallerY=0; smallerY<keyImgHeight; smallerY++) {
			biggerY = y+smallerY;
			for(int smallerX=0; smallerX<keyImgWidth; smallerX++) {
				biggerX = x+smallerX;
				if(biggerY>=tocompareHeight || biggerX>=tocompareWidth) {
					return false;
				}
				xor = keyImageRGBData[smallerY][smallerX]^tocompareImageRGBData[biggerY][biggerX];
				if(xor!=0) {
					return false;
				}
			}
			biggerX = x;
		}
		return true;
	}

}
